<?php
/**
 * 代码solution管理
 * User: cqfut
 * Date: 2020/2/15
 * Time: 17:23
 */
require_once (ROOTDIR."common/db_utils.php");
require_once (ROOTDIR."config/sys_config.php");

class SolutionModel
{
    public function __construct()
    {

    }

    public function getSolutionInfo($solutionId, $userId)
    {
        // 获取 solution 对应的 problem_id
        $colNames = array('problem_id', 'language');
        $sql = DbUtil::genSelectSql($colNames, "solution");
        $sql.= " where user_id=? and solution_id=?";
        $result = DbUtil::getInstance()->query($sql, $userId, $solutionId);
        if ( count($result) == 0 ) {
            return null;
        }

        $row = $result[0];
        $problemId = intval($row['problem_id']);
        $language = intval($row['language']); // 整数

        // 获取题目信息
        $problemTitle = "";
        $sql = "select `title` from problem where problem_id=?";
        $result = DbUtil::getInstance()->query($sql, $problemId);
        if ( count($result) > 0 ) {
            $row = $result[0];
            $problemTitle = $row['title']; // urlencode(
        }

        // 获取 solution 对应的代码
        $sourceCode = "";
        $sql = "select `source` from source_code_user where solution_id=?";
        $result = DbUtil::getInstance()->query($sql, $solutionId);
        if ( count($result) > 0 ) {
            $row = $result[0];
            $sourceCode = $row['source']; // urlencode(
        }

        // 构建返回数据包
        $solutionInfo =array();
        $solutionInfo['problem_id'] = $problemId;
        $solutionInfo['problem_title'] = urlencode($problemTitle);
        $solutionInfo['source_code'] = urlencode(base64_encode($sourceCode));
        $solutionInfo['language'] = $language;
        return $solutionInfo;
    }

    public function verifySourceCode($source) {
        // 限制提交内容：过滤恶意提交，避免提交无聊代码
        $ret = preg_match("/.*\s{80,}/i", $source, $match);
        $ret |= preg_match("/[a-z A-Z 0-9]{150,}/i", $source, $match);
        // 过滤关键函数
        $ret |= preg_match("/system/i", $source, $match);
        $ret |= preg_match("/exec/i", $source, $match);
        $ret |= preg_match("/execl/i", $source, $match);
        $ret |= preg_match("/unistd/i", $source, $match);
        $ret |= preg_match("/reboot/i", $source, $match);
        $ret |= preg_match("/shutdown/i", $source, $match);
        if ( $ret ) {
            return '请注意代码的提交格式,不要胡乱提交代码';
        }

        // 代码不应太短或者太长
        $len=strlen($source);
        if ($len < 10) {
            return 'Code too short!';
        }
        if ($len > 65536 ) {
            return 'Code too long!';
        }
        return null;
    }

    public function rejudgeSolution($solutionId, $code, $enableO2, $userId)
    {
        // 校验是否具有更改权限
        $sql = "select count(*) from solution where user_id=? and solution_id=?";
        $result = DbUtil::getInstance()->query($sql, $userId, $solutionId);
        if (count($result) == 0 || intval($result[0][0]) == 0) {
            return -1; // 不存在指定的 solution
        }

        // 更改 solution 对应的 source
        if ($code != null) {
            // 更新 table source_code_user
            $sql = "update source_code_user set `source`=? where solution_id=?";
            DbUtil::getInstance()->query($sql, $code, $solutionId);

            // 更新 table source_code
            $sql = "update source_code set `source`=? where solution_id=?";
            DbUtil::getInstance()->query($sql, $code, $solutionId);
        }

        $sql = "update solution set `result`=0, `o2_flag`=? where solution_id=?";
        DbUtil::getInstance()->query($sql, $enableO2, $solutionId);
        return 0;
    }

    public function getJudgeStatus($solutionId) {
        // 查看 solution 状态
        $sql = "select `result`, `time`, `memory`, `in_date`, `judger` from solution where solution_id=?";
        $result = DbUtil::getInstance()->query($sql, $solutionId);
        // 不存在指定的 solution
        if (count($result) == 0 ) {
            return null;
        }
        $row = $result[0];
        $statusInfo =array();
        $statusInfo['result'] = intval($row['result']); // 评测结果
        $statusInfo['time'] = intval($row['time']); // 运行耗时
        $statusInfo['memory'] = intval($row['memory']); // 占用内存
        $statusInfo['in_date'] = $row['in_date']; // 提交时间
        $statusInfo['judger'] = $row['judger']; // 评测主机
        return $statusInfo;
    }
}